import 'dart:async';
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:xsdk_flutter/xsdk_splashAd.dart';
import 'package:xsdk_flutter/xsdk_videoAd.dart';
import 'xsdk_banner.dart';

import 'xsdk_flutter_platform_interface.dart';

/// An implementation of [XsdkFlutterPlatform] that uses method channels.
class MethodChannelXsdkFlutter extends XsdkFlutterPlatform {
  /// The method channel used to interact with the native platform.
  @visibleForTesting
  final methodChannel = const MethodChannel('xsdk_flutter');
  final eventChannel = const EventChannel('xsdk_flutter_event');
  StreamSubscription<dynamic>? streamSubscription;

  static Map<int, BannerAd> bannerAdMap = <int, BannerAd>{};
  static Map<int, VideoAd> videoAdMap = <int, VideoAd>{};
  static Map<int, SplashAd> splashAdMap = <int, SplashAd>{};

  EventHandler? _onRegisterSucceed;
  EventHandler? _onNotificationMessageClicked;
  EventHandler? _onNotificationMessageArrived;

  void Function(Map)? _onIAPEvent;

  MethodChannelXsdkFlutter() {
    streamSubscription = eventChannel?.receiveBroadcastStream().listen((event) {
      Map data = jsonDecode(event);
      if (data.containsKey("event")) {
        var event = data["event"] as String;

        if ("createBannerAd".compareTo(event) == 0) {
          var objectId = data["objectId"] as int;
          bannerAdMap[objectId]?.onCreateEvent(data);
        } else if ("createRewardedVideoAd".compareTo(event) == 0) {
          var objectId = data["objectId"] as int;
          videoAdMap[objectId]?.onCreateEvent(data);
        } else if ("createSplashAD".compareTo(event) == 0) {
          var objectId = data["objectId"] as int;
          splashAdMap[objectId]?.onCreateEvent(data);
        } else if ("onIAPEvent".compareTo(event) == 0) {
          _onIAPEvent?.call( jsonDecode(data["data"])  as Map);
        }
      }
    }) as StreamSubscription;
  }

  //推送的接口需要修改
  @override
  onPush({
    required EventHandler onRegisterSucceed,
    required EventHandler onNotificationMessageClicked,
    required EventHandler onNotificationMessageArrived,
  }) {
    _onRegisterSucceed = onRegisterSucceed;
    _onNotificationMessageClicked = onNotificationMessageClicked;
    _onNotificationMessageArrived = onNotificationMessageArrived;
    methodChannel.setMethodCallHandler(_handleMethod);
  }

  Future<dynamic> _handleMethod(MethodCall call) async {
    switch (call.method) {
      case "onRegisterSucceed":
        return _onRegisterSucceed ?? (call.arguments.cast<String>());
      case "onNotificationMessageClicked":
        return _onNotificationMessageClicked ?? (call.arguments.cast<String>());
      case "onNotificationMessageArrived":
        return _onNotificationMessageArrived ?? (call.arguments.cast<String>());
      case "createBannerAd_callback":
        String jsonStr = call.arguments.cast<String>();
        Map<String, dynamic> data = jsonDecode(jsonStr);
        var banner = bannerAdMap[data['objectId']];
        if (banner != null) {
          banner.onCreateEvent(data);
        }
        return;

      default:
        throw UnsupportedError("Unrecognized Event");
    }
  }

  @override
  Future<String?> getPlatformVersion() async {
    final version =
        await methodChannel.invokeMethod<String>('getPlatformVersion');
    return version;
  }

  // 是否存在某个sdk
  @override
  Future<bool?> hasSDK(
      {required String service, required String provider}) async {
    return await methodChannel.invokeMethod<bool>(
        'hasSDK', jsonEncode({'service': service, 'provider': provider}));
  }

  @override
  Future<bool?> isInitSDK(
      {required String service, required String provider}) async {
    return await methodChannel.invokeMethod<bool>(
        'isInitSDK', jsonEncode({'service': service, 'provider': provider}));
  }

  @override
  Future<void> init() async {
    return await methodChannel.invokeMethod<void>('init');
  }

  @override
  Future<String?> initSDK(Map data) async {
    return await methodChannel.invokeMethod<String>(
        'initSDK', jsonEncode(data));
  }

  // 是否存在某个sdk
  @override
  Future<String?> login(Map data) async {
    return await methodChannel.invokeMethod<String>('login', jsonEncode(data));
  }

  @override
  Future<String?> logout(Map data) async {
    return await methodChannel.invokeMethod<String>('logout', jsonEncode(data));
  }

  @override
  Future<String?> pay(Map data) async {
    return await methodChannel.invokeMethod<String>('pay', jsonEncode(data));
  }

  @override
  Future<String?> finishPay(Map data) async {
    return await methodChannel.invokeMethod<String>(
        'finishPay', jsonEncode(data));
  }

  @override
  Future<String?> share(Map data) async {
    return await methodChannel.invokeMethod<String>('share', jsonEncode(data));
  }

  //=======================内购类的==================================
  @override
  Future<String?> requestProduct(Map data) async {
    return await methodChannel.invokeMethod<String>(
        'requestProduct', jsonEncode(data));
  }

  @override
  Future<String?> queryProduct(Map data) async {
    return await methodChannel.invokeMethod<String>(
        'queryProduct', jsonEncode(data));
  }

  @override
  void onIPAEvent({void Function(Map)? onEvent}) async {
    _onIAPEvent = onEvent;
    return await methodChannel.invokeMethod('onIPAEvent');
  }

  //================================================================

  @override
  Future<void> postEvent(Map data) async {
    return await methodChannel.invokeMethod<void>(
        'postEvent', jsonEncode(data));
  }

  Future<BannerAd?> createBannerAd(Map data,
      {void Function(String)? onLoad,
      void Function()? onHide,
      void Function(String)? onError}) async {
    int? objectId = await methodChannel.invokeMethod<int?>(
        'createBannerAd', jsonEncode(data));
    if (objectId == null) return null;
    var banner = BannerAd(
        objectId: objectId,
        methodChannel: methodChannel,
        onLoad: onLoad,
        onHide: onHide,
        onError: onError);
    bannerAdMap[objectId] = banner;
    return banner;
  }

  Future<VideoAd?> createVideoAd(Map data,
      {void Function(String)? onLoad,
      void Function()? onReward,
      void Function()? onClose,
      void Function(String)? onError}) async {
    int? objectId = await methodChannel.invokeMethod<int?>(
        'createRewardedVideoAd', jsonEncode(data));
    if (objectId == null) return null;
    var videoAd = VideoAd(
        objectId: objectId,
        methodChannel: methodChannel,
        onLoad: onLoad,
        onClose: onClose,
        onError: onError,
        onReward: onReward);
    videoAdMap[objectId] = videoAd;
    return videoAd;
  }

  Future<SplashAd?> createSplashAd(Map data,
      {void Function(String)? onLoad,
      void Function()? onClicked,
      void Function()? onDismissed,
      void Function(String)? onError}) async {
    int? objectId = await methodChannel.invokeMethod<int?>(
        'createSplashAD', jsonEncode(data));
    if (objectId == null) return null;
    var splashAd = SplashAd(
        objectId: objectId,
        methodChannel: methodChannel,
        onLoad: onLoad,
        onDismissed: onDismissed,
        onClicked: onClicked,
        onError: onError);
    splashAdMap[objectId] = splashAd;
    return splashAd;
  }
}
